<!DOCTYPE html>
<html>
  <head>
    <title>Listing 10.5</title>
    <script type="text/javascript" src="../scripts/assert.js"></script>
    <link href="../styles/assert.css" rel="stylesheet" type="text/css">
  </head>
  <body>
    <script type="text/javascript">

      (function () {
        var cache = {};

        this.tmpl = function tmpl(str, data) {

          //
          // Figure out if we're getting a template, or if we need to
          // load the template - and be sure to cache the result.
          //
          var fn = !/\W/.test(str) ?
              cache[str] = cache[str] ||
                  tmpl(document.getElementById(str).innerHTML) :

            //
            // Generate a reusable function that will serve as a template
            // generator (and which will be cached).
            //
              new Function("obj",
                  "var p=[],print=function(){p.push.apply(p,arguments);};" +

                    // Introduce the data as local variables using with
                      "with(obj){p.push('" +

                    // Convert the template into pure JavaScript
                      str
                          .replace(/[\r\t\n]/g, " ")
                          .split("<%").join("\t")
                          .replace(/((^|%>)[^\t]*)'/g, "$1\r")
                          .replace(/\t=(.*?)%>/g, "',$1,'")
                          .split("\t").join("');")
                          .split("%>").join("p.push('")
                          .split("\r").join("\\'")
                      + "');}return p.join('');");

          // Provide some basic currying to the user
          return data ? fn(data) : fn;
        };
      })();

      assert(tmpl("Hello, <%= name %>!", {name:"world"}) ==
          "Hello, world!", "Do simple variable inclusion.");

      var hello = tmpl("Hello, <%= name %>!");
      assert(hello({name:"world"}) == "Hello, world!",
          "Use a pre-compiled template.");


    </script>
  </body>
</html>

